package com.cpkf.util.iTextPDF;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

import org.apache.commons.io.FileUtils;
import org.json.JSONArray;
import org.json.JSONException;

import com.itextpdf.text.Chapter;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.ListItem;
import com.itextpdf.text.Section;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.tool.xml.XMLWorkerHelper;

/**
 * export PDF entrance, this class initialize the PDFCreator and export PDF by different way
 *
 * @author Hyman Hu
 * @since  2014-6-23
 * Copyright SHOP.COM: all rights reserved worldwide
 */
public class ExportPdf {

	/**
	 * create pdf file, and get file output stream
	 * 
	 * @param pdfTitle						the PDF file name will be created by pdfTitle, For example, pdfTitle = 'Export PDF Test',
	 * 										then the PDF file name is 'Export_PDF_Test.pdf'
	 * @param filePath						this is path of pdf, like 'D:\\testFolder' or '\\testFolder' or 'D:\\testFolder\\'
	 * @return OutputStream
	 * @throws FileNotFoundException
	 */
	public static OutputStream createOutputStream(String pdfTitle, String filePath) throws FileNotFoundException {
		OutputStream os = null;
		if (!filePath.isEmpty()) {
			String directory = filePath;
			if (filePath.endsWith(".pdf") || filePath.endsWith("\\")) {
				directory = filePath.substring(0, filePath.lastIndexOf("\\"));
			}
			File file = new File(filePath);
			if (!file.exists()) {
				file.mkdirs();
			}

			os = new FileOutputStream(String.format("%s%s%s%s", directory, "\\", pdfTitle.replaceAll(" ", "_"), ".pdf"));
		}
		return os;
	}

	/**
	 * export PDF from html inputstream
	 * 
	 * @param pdfTitle					title of PDF
	 * @param filePath					this is path of pdf
	 * @param htmlFileStream			inputstream from read html
	 * @throws IOException
	 * @throws DocumentException
	 */
	public static void exportHtml2Pdf(String pdfTitle, String filePath, InputStream htmlFileStream) throws IOException,
			DocumentException {

		PDFCreator pdfCreator = new PDFCreator();
		Document document = pdfCreator.initDocument(pdfTitle, createOutputStream(pdfTitle, filePath));

		InputStreamReader isr = new InputStreamReader(htmlFileStream, "UTF-8");
		XMLWorkerHelper.getInstance().parseXHtml(pdfCreator.getPdfWriter(), document, isr);

		pdfCreator.closeDocument(document);
	}

	/**
	 * export PDF from html url
	 * 
	 * @param pdfTitle				title of PDF
	 * @param filePath				this is path of pdf
	 * @param requestUrl			local url or remote url
	 * @throws IOException
	 * @throws DocumentException
	 */
	public static void exportHtml2Pdf(String pdfTitle, String filePath, String requestUrl) throws IOException,
			DocumentException {
		InputStream htmlFileStream = null;
		String URLRegex = "^(https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]";
		Pattern pattern = Pattern.compile(URLRegex);
		if (pattern.matcher(requestUrl).matches()) {
			htmlFileStream = HttpClientUtil.doURLPost(requestUrl);
		} else {
			htmlFileStream = new FileInputStream(requestUrl);
		}

		exportHtml2Pdf(pdfTitle, filePath, htmlFileStream);
	}

	/**
	 * export PDF from xml, the root element name is the directory title, the second level element is chapter, the third level 
	 * element is section, the fourth level is subsection, the fifth level is list, other is content
	 * 
	 * @param pdfTitle						title of PDF
	 * @param pdfFilePath					this is path of pdf
	 * @param xmlPath						xml file's address, like 'D:\\apache-tomcat-7.0.53\\conf\\web.xml'
	 * @throws FileNotFoundException
	 * @throws DocumentException
	 * @throws org.dom4j.DocumentException
	 */
	public static void exportXml2Pdf(String pdfTitle, String pdfFilePath, String xmlPath) throws FileNotFoundException,
			DocumentException, org.dom4j.DocumentException {
		PDFCreator pdfCreator = new PDFCreator();
		Document document = pdfCreator.initDocument(pdfTitle, createOutputStream(pdfTitle, pdfFilePath));

		List<org.dom4j.Element> elementList = new ArrayList<org.dom4j.Element>();
		org.dom4j.Document dom4jDocument = XmlUtil.getDocument(xmlPath);
		org.dom4j.Element rootElement = XmlUtil.getRootElement(dom4jDocument);
		String chapterRootTitle = rootElement.getName();
		XmlUtil.getElements(rootElement, elementList);
		
		if (!elementList.isEmpty()) {
			Chapter chapter = null;
			Section section = null;
			Section subsection = null;
			com.itextpdf.text.List list = new com.itextpdf.text.List(true, 20);;
			List<Chapter> chapters = new ArrayList<Chapter>();
			for (org.dom4j.Element element : elementList) {
				String depth = element.attributeValue("depth");
				if ("2".equals(depth)) {
					chapter = pdfCreator.createChapter(document, element.getName());
					pdfCreator.addContent(chapter, XmlUtil.getElementInfo(element));
					chapters.add(chapter);
				} else if ("3".equals(depth)) {
					section = pdfCreator.addSection(chapter, element.getName());
					pdfCreator.addContent(section, XmlUtil.getElementInfo(element));
				} else if ("4".equals(depth)) {
					subsection = pdfCreator.addSubsection(section, element.getName());
					pdfCreator.addContent(subsection, XmlUtil.getElementInfo(element));
				} else if (Integer.parseInt(depth) > 4) {
					if (element != null) {
						list.add(new ListItem(XmlUtil.getElementInfo(element)));
						pdfCreator.addContent(subsection, list);
					}
				}
			}
			for (Chapter chapterTemp : chapters) {
				pdfCreator.addContent(document, chapterTemp);
			}
			pdfCreator.addDirectory(document, chapterRootTitle);
		}
		pdfCreator.closeDocument(document);
	}
	
	/**
	 * export PDF from text template, the rule refer to TextAnalyzeUtil
	 * 
	 * @param pdfTitle				title of PDF
	 * @param pdfFilePath			this is path of pdf
	 * @param textPath				text file's address, like 'D:\\testFolder\\test.txt'
	 * @throws DocumentException
	 * @throws IOException
	 */
	public static void exportTextTemplate2Pdf(String pdfTitle, String pdfFilePath, String textPath) throws DocumentException, IOException {
		File file = new File(textPath);
		if (!file.exists()) {
			return;
		}
		
		PDFCreator pdfCreator = new PDFCreator();
		Document document = pdfCreator.initDocument(pdfTitle, createOutputStream(pdfTitle, pdfFilePath));
		
		List<String> lines = FileUtils.readLines(file, "UTF-8");
		Chapter chapter = null;
		Section section = null;
		Section subsection = null;
		int currentChapter = 0;
		com.itextpdf.text.List list = new com.itextpdf.text.List(true, 20);
		String chapterRootTitle = "";
		List<Chapter> chapters = new ArrayList<Chapter>();
		boolean isList = false;
		boolean added = false;
		for (String line : lines) {
			if (!isList) {
				added = false;
				list = new com.itextpdf.text.List(true, 20);
			} else {
				if (!added) {
					added = true;
					if (currentChapter == 0) {
						pdfCreator.addContent(chapter, list);
					} else if (currentChapter == 1) {
						pdfCreator.addContent(section, list);
					} else if (currentChapter == 2) {
						pdfCreator.addContent(subsection, list);
					}
				}
			}
			
			ElementCategory elementCategoriy = TextAnalyzeUtil.judgeCategory(line);
			if (elementCategoriy.categoryId == 0) {
				isList = false;
				chapterRootTitle = TextAnalyzeUtil.getTitle(line);
			} else if (elementCategoriy.categoryId == 1) {
				isList = false;
				chapter = pdfCreator.createChapter(document, TextAnalyzeUtil.getChapter(line));
				chapters.add(chapter);
				currentChapter = 0;
			} else if (elementCategoriy.categoryId == 2) {
				isList = false;
				section = pdfCreator.addSection(chapter, TextAnalyzeUtil.getSection(line));
				currentChapter = 1;
			} else if (elementCategoriy.categoryId == 3) {
				isList = false;
				subsection = pdfCreator.addSubsection(section, TextAnalyzeUtil.getSubsection(line));
				currentChapter = 2;
			} else if (elementCategoriy.categoryId == 7) {
				isList = false;
				if (currentChapter == 0) {
					pdfCreator.addContent(chapter, line);
				} else if (currentChapter == 1) {
					pdfCreator.addContent(section, line);
				} else if (currentChapter == 2) {
					pdfCreator.addContent(subsection, line);
				}
			} else if (elementCategoriy.categoryId == 4) {
				isList = true;
				list.add(TextAnalyzeUtil.getListChild(line));
			}
		}
		
		for (Chapter chapterTemp : chapters) {
			pdfCreator.addContent(document, chapterTemp);
		}
		pdfCreator.addDirectory(document, chapterRootTitle);
		
		pdfCreator.closeDocument(document);
	}
	
	/**
	 * export PDF from JsonText, the text must jsonArray string
	 * 
	 * @param pdfTitle					title of PDF
	 * @param pdfFilePath				this is path of pdf
	 * @param textPath					text file's address, like 'D:\\testFolder\\test.txt'
	 * @throws DocumentException
	 * @throws IOException
	 * @throws JSONException 
	 */
	public static void exportJsonText2Pdf(String pdfTitle, String pdfFilePath, String textPath, float totalWidth, float[] columnWidth) 
			throws DocumentException, IOException, JSONException {
		File file = new File(textPath);
		if (!file.exists()) {
			return;
		}
		
		PDFCreator pdfCreator = new PDFCreator();
		Document document = pdfCreator.initDocument(pdfTitle, createOutputStream(pdfTitle, pdfFilePath));
		
		pdfCreator.addPdfTitle(document, pdfTitle);
		pdfCreator.createSeparatorLine(document);
		
		String result = FileUtils.readFileToString(file, "UTF-8");
		JSONArray jsonArray = DataConvertUtil.convertToJSONArray(result.trim());
		PdfPTable pdfPTable = pdfCreator.createTable(jsonArray);
		pdfCreator.setTableWidth(pdfPTable, totalWidth, columnWidth);
		pdfCreator.addContent(document, pdfPTable);

		pdfCreator.closeDocument(document);
	}
	
	/**
	 * export PDF from JsonText, the text must jsonArray string
	 * 
	 * @param pdfTitle					title of PDF
	 * @param pdfFilePath				this is path of pdf
	 * @param textPath					text file's address, like 'D:\\testFolder\\test.txt'
	 * @param headers					the table's headers
	 * @throws DocumentException
	 * @throws IOException* 
	 * @throws JSONException 
	 */
	public static void exportJsonText2Pdf(String pdfTitle, String pdfFilePath, String textPath, List<String> headers, float totalWidth, float[] columnWidth) 
			throws DocumentException, IOException, JSONException {
		File file = new File(textPath);
		if (!file.exists()) {
			return;
		}
		
		PDFCreator pdfCreator = new PDFCreator();
		Document document = pdfCreator.initDocument(pdfTitle, createOutputStream(pdfTitle, pdfFilePath));
		
		pdfCreator.addPdfTitle(document, pdfTitle);
		pdfCreator.createSeparatorLine(document);
		
		String result = FileUtils.readFileToString(file, "UTF-8");
		JSONArray jsonArray = DataConvertUtil.convertToJSONArray(result.trim());
		PdfPTable pdfPTable = pdfCreator.createTable(headers, jsonArray);
		pdfCreator.setTableWidth(pdfPTable, totalWidth, columnWidth);
		pdfCreator.addContent(document, pdfPTable);
		
		pdfCreator.closeDocument(document);
	}
	
	public static void main(String[] args) {
		try {
			// Demo1: export jsonarray text to pdf
			ExportPdf.exportJsonText2Pdf("Export Json Text to PDF1", "D:\\testFolder", "D:\\testFolder\\jsonArrayTest.json", 500f, null);
			
			// Demo2: export jsonarray text to pdf, customize the headers of table
			List<String> headers = new ArrayList<String>();
			headers.add("macatalog");
			headers.add("ecommerce");
			headers.add("bv");
			headers.add("webLevel");
			headers.add("isMACatalog");
			headers.add("ibv");
			headers.add("isOnecart");
			headers.add("catalogName");
			headers.add("isEcommerce");
			headers.add("onecart");
			headers.add("catalogId");
			headers.add("dealsAvailable");
			ExportPdf.exportJsonText2Pdf("Export Json Text to PDF2", "D:\\testFolder", "D:\\testFolder\\jsonArrayTest.json", headers, 500f, null);
			
			// Demo3: export xml to pdf
			ExportPdf.exportXml2Pdf("Export Xml to PDF", "D:\\testFolder", "D:\\apache-tomcat-7.0.53\\conf\\web.xml");
			
			// Demo4: export text template to pdf
			ExportPdf.exportTextTemplate2Pdf("Export Text Template to PDF", "D:\\testFolder", "D:\\testFolder\\textTemplate.txt");
			
			// Demo5: export html to pdf
			ExportPdf.exportHtml2Pdf("Export Html to PDF", "D:\\testFolder", "http://maven.apache.org/");
		} catch (DocumentException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (org.dom4j.DocumentException e) {
			e.printStackTrace();
		} catch (JSONException e) {
			e.printStackTrace();
		}
		
	}
}
